//
// File:	main.cpp
// Author:	Thomas TISSOT-DUPONT
// Login:	<thomas.tissotdupont@free.fr>
//
// Create:	20/01/2010 at 21:44:14
// Purpose:	
//
#include <QtGui/QApplication>
#include <iostream>
#include "Base.hpp"
#include "Engine.hpp"
#include "Config.hpp"
#include "Global.hpp"
#include "DisplayManager.hpp"
#include "GuiManager.hpp"
#include "GuiMenuMain.hpp"
#include "GuiMenuOptions.hpp"
#include "GuiMenuCreateGame.hpp"
#include "Inputs.hpp"
#include "InputManager.hpp"
#include "EntityFactory.hpp"
#include "EntityManager.hpp"
#include "GameRuleManager.hpp"
#include "SoundManager.hpp"
#include "EventManager.hpp"
#include "FactoryManager.hpp"
#include "SDK.hpp"
#include "Trace.hpp"

int main(int argc, char *argv[])
{
#ifndef NDEBUG
	Trace::setLevel(Trace::All);
#else
	Trace::setLevel(Trace::None);
#endif

	//QTApplication
	QApplication application(argc, argv);

	//Instanciate global pointers
	GlobalVariables::Engine::Acquire(new Engine());
	GlobalVariables::FactoryManager::Acquire(new FactoryManager());
	GlobalVariables::Config::Acquire(new Config());
	GlobalVariables::Global::Acquire(new Global());
	GlobalVariables::DisplayManager::Acquire(new DisplayManager());
	GlobalVariables::InputManager::Acquire(new InputManager());
	GlobalVariables::GuiManager::Acquire(new GuiManager());
	GlobalVariables::EntityManager::Acquire(new EntityManager());
	GlobalVariables::GameRuleManager::Acquire(new GameRuleManager());
	GlobalVariables::SoundManager::Acquire(new SoundManager());
	GlobalVariables::EventManager::Acquire(new EventManager());

	try
	{
		//Configuration
		GlobalVariables::Config::Get().ParseFromFile(Config::GetConfigFilePath());

		//Input
		InputManager *pInputManager = dynamic_cast<InputManager *>(&GlobalVariables::InputManager::Get());
		if (pInputManager != NULL)
		{
			pInputManager->AddInput(new InputKeyboard());
			pInputManager->AddInput(new InputMouse());

			//Read the keyboard bindings from configuration
			InputKeyboard::BindingMapType::const_iterator kbIt = InputKeyboard::GetBindingNames().begin();
			InputKeyboard::BindingMapType::const_iterator kbIte = InputKeyboard::GetBindingNames().end();
			for (; kbIt != kbIte; ++kbIt)
			{
				if (GlobalVariables::Config::Get().HasCvar(kbIt->first))
					pInputManager->Bind(kbIt->second, GlobalVariables::Config::Get().GetCvar(kbIt->first));
			}

			//Read the mouse bindings from configuration
			InputMouse::BindingMapType::const_iterator mouseIt = InputMouse::GetBindingNames().begin();
			InputMouse::BindingMapType::const_iterator mouseIte = InputMouse::GetBindingNames().end();
			for (; mouseIt != mouseIte; ++mouseIt)
			{
				if (GlobalVariables::Config::Get().HasCvar(mouseIt->first))
					pInputManager->Bind(mouseIt->second, GlobalVariables::Config::Get().GetCvar(mouseIt->first));
			}
		}

		//Create Window (UNDONE: allow the user to specify their own screen size in the options menu)
		GlobalVariables::DisplayManager::Get().InitWindow("R.TYPE", 800, 600, GlobalVariables::Config::Get().GetCvar("r_fullscreen", false));

		//Setup View
		GlobalVariables::DisplayManager::Get().GetView()->SetViewCenterX(GlobalVariables::DisplayManager::Get().GetWindow()->GetReferenceWidth() * 0.5f);
		GlobalVariables::DisplayManager::Get().GetView()->SetViewCenterY(GlobalVariables::DisplayManager::Get().GetWindow()->GetReferenceHeight() * 0.5f);
		GlobalVariables::DisplayManager::Get().GetView()->SetViewWidth(GlobalVariables::DisplayManager::Get().GetWindow()->GetReferenceWidth());
		GlobalVariables::DisplayManager::Get().GetView()->SetViewHeight(GlobalVariables::DisplayManager::Get().GetWindow()->GetReferenceHeight());

		//GUI
		GlobalVariables::GuiManager::Get().Init(true);
		GlobalVariables::GuiManager::Get().AddPanel("menumain", new GuiMenuMain());
		GlobalVariables::GuiManager::Get().AddPanel("menuoptions", new GuiMenuOptions());
		GlobalVariables::GuiManager::Get().AddPanel("menucreategame", new GuiMenuCreateGame());
		GlobalVariables::GuiManager::Get().ShowPanel("menumain");

		//Load the SDK
		ISDK *pSDK = new SDK();
		if (pSDK->Load("sdk.dll", "SDKMain"))
		{
			//Run Engine
			GlobalVariables::Engine::Get().Start();
			GlobalVariables::Engine::Get().Run();
		}
		delete pSDK;
	}
	catch (GlobalVariables::Exception *pException)
	{
		Trace::error << "FATAL EXCEPTION: " << pException->what() << std::endl;
	}
	return EXIT_SUCCESS;
}
